/* domain
        Dom_Node = Node &        
        Dom_Empty = Empty
*/
  
sealed abstract class BT {
  def isNode(): Boolean = (this : BT) match {
    case Node(_,_) if new Node(new Empty(),new Empty()).left.isInstanceOf[Empty] => true
    case Empty() => false
  }
  
  def isNode2(): Boolean = (this : BT) match {
    case n: Node if n.isInstanceOf[Node] => true
    case Empty() => false
  }
  
  def isNode3(): Boolean = (this : BT) match {
    case n: Node if this.isZero(3) => true
    case n: Node if !this.isZero(2) => true
    case Empty() => false
  }
  
  def isZero(n: Int): Boolean = 
    /* postcondition n == 0 <--> res == true
     */
     n == 0
     
  def isNode4(): Boolean = (this : BT) match {
    case n: Node if this.getZero(5) == 0 => true
    case Empty() => false
  }
   
  def getZero(n: Int): Int = 
    /* postcondition res == 0
     */
    0
   
  def isNode5(): Boolean = (this : BT) match {
    case n: Node if this.isZero(0)   => true
    case Empty() => false
  }  
 
  def isNode6(): Boolean = (this : BT) match {
    case n: Node if new Dummy(true && this.isZero(0)).b   => true
    case Empty() => false
  }
    
  def isNode7(): Boolean = (this : BT) match {
    case n: Node if 3+2 == 5   => true
    case Empty() => false
  }  
  
  def isNode8(): Boolean = (this : BT) match {
    case n: Node if this.isZero(0) && this.isZero(0)   => true
    case Empty() => false
  } 
  
  def isNode9(): Boolean = (this : BT) match {
    case n: Node if this.isZero(4) || this.isZero(0)   => true
    case Empty() => false
  } 
  
  def isNode10(): Boolean = (this : BT) match {
    case n: Node if this.isZero(0) && !this.isZero(4)   => true
    case Empty() => false
  } 
}
class Empty extends BT
class Node(val left: BT, val right: BT) extends BT

class Dummy(val b: Boolean) {}

object Node {
  
  def apply(left: BT, right: BT): Node = 
    new Node(left,right)
    
  def unapply(n: Node): Option[(BT,BT)] =
    Some(Tuple2(n.left,n.right))
}

object Empty {
  def apply(): Empty = new Empty()
  
  def unapply(e: Empty): Boolean =    
    e.isInstanceOf[Empty]
}

object New {

  def main(args: Array[String]): Unit = 
    Node(Node(Empty(),Empty()),Empty()).isNode()
}



